#ifndef __KEYBOARD_H
#define __KEYBOARD_H

#include "stm32f10x.h"                  // Device header


/*
按键滤波时间50ms, 单位10ms。
只有连续检测到50ms状态不变才认为有效，包括弹起和按下两种事件
即使按键电路不做硬件滤波，该滤波机制也可以保证可靠地检测到按键事件
*/
#define KEY_FILTER_TIME   5
#define KEY_LONG_TIME     100           /* 单位10ms， 持续1秒，认为长按事件 */

/*
每个按键对应1个全局的结构体变量。
*/
typedef struct
{
    /* 下面是一个函数指针，指向判断按键手否按下的函数 */
    uint8_t(*IsKeyDownFunc)(void); /* 按键按下的判断函数,1表示按下 */

    uint8_t  Count;         /* 滤波器计数器 */
    uint16_t LongCount;     /* 长按计数器 */
    uint16_t LongTime;      /* 按键按下持续时间, 0表示不检测长按 */
    uint8_t  State;         /* 按键当前状态（按下还是弹起） */
    uint8_t  RepeatSpeed;   /* 连续按键周期 */
    uint8_t  RepeatCount;   /* 连续按键计数器 */
}KEY_T;

/*
定义键值代码, 必须按如下次序定义每个键的按下、弹起和长按事件

推荐使用enum, 不用#define，原因：
(1) 便于新增键值,方便调整顺序，使代码看起来舒服点
(2) 编译器可帮我们避免键值重复。
*/
typedef enum
{
    KEY_NONE = 0,           /* 0 表示按键事件 */

    KEY_L_DOWN,             /* L键按下 */
    KEY_L_UP,               /* L键弹起 */
    KEY_L_LONG,             /* L键长按 */

    KEY_R_DOWN,             /* R键按下 */
    KEY_R_UP,               /* R键弹起 */
    KEY_R_LONG,             /* R键长按 */

    KEY_U_DOWN,             /* U键按下 */
    KEY_U_UP,               /* U键弹起 */
    KEY_U_LONG,             /* U键长按 */

    KEY_D_DOWN,             /* D键按下 */
    KEY_D_UP,               /* D键弹起 */
    KEY_D_LONG,             /* D键长按 */

    KEY_C_DOWN,             /* C键按下 */
    KEY_C_UP,               /* C键弹起 */
    KEY_C_LONG             /* C键长按 */

}KEY_ENUM;


/* 按键FIFO用到变量 */
#define KEY_FIFO_SIZE   5
#define KEY_COUNT       5         /* 按键个数, 8个独立建 + 2个组合键 */

typedef struct
{
    uint8_t Buf[KEY_FIFO_SIZE];     /* 键值缓冲区 */
    uint8_t Read;                   /* 缓冲区读指针1 */
    uint8_t Write;                  /* 缓冲区写指针 */
    uint8_t Read2;                  /* 缓冲区读指针2 */
}KEY_FIFO_T;

/* 供外部调用的函数声明 */
//void InitKey(void);
void KeyScan(void);
void PutKey(uint8_t _KeyCode);
KEY_ENUM kbd_GetKey(void);
uint8_t kbd_GetKey2(void);
void SetKeyParam(uint8_t _ucKeyID, uint16_t _LongTime, uint8_t  _RepeatSpeed);
void ClearKey(void);

//#define  WAIT_FOR_RESET()     while(1){}
#define  WAIT_KEY_C()      while(!(KEY_C_DOWN == kbd_GetKey())){}
#define  WAIT_KEY_LR()     while(!(KEY_L_DOWN == kbd_GetKey()) || !(KEY_R_DOWN == kbd_GetKey()) ){}
#define  WAIT_KEY_UDC()     while(!(KEY_U_DOWN == kbd_GetKey()) || !(KEY_D_DOWN == kbd_GetKey()|| !(KEY_C_DOWN == kbd_GetKey()) ){}
#define IS_KEY_C()		(0)

void kbd_init(void);
void PrintKeyStatu(void);



#endif /* KEYBOARD_H_ */


